package com.cupdata.zicon.jdk7concurrent.chapter1;

import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;

/**
 * The ThreadFactory interface has only one method called newThread. It receives a
Runnable object as a parameter and returns a Thread object. When you implement a
ThreadFactory interface, you have to implement that interface and override this method.
Most basic ThreadFactory, has only one line.
return new Thread(r);
You can improve this implementation by adding some variants by:
 1 Creating personalized threads, as in the example, using a special format for the name
or even creating our own thread class that inherits the Java Thread class
 2 Saving thread creation statistics, as shown in the previous example
 3 Limiting the number of threads created
 4 Validating the creation of the threads
 5 And anything more you can imagine
The use of the factory design pattern is a good programming practice but, if you implement a
ThreadFactory interface to centralize the creation of threads, you have to review the code
to guarantee that all threads are created using that factory.
 * @author SunYabing
 *
 */
public class ThreadFactotyTest {

	//@Test
	public static void  main(String[] args) {
		MyThreadFactory factory = new MyThreadFactory("MyThreadFactory");
		Task456 task = new Task456();

		Thread thread;
		System.out.printf("Starting the Threads\n");
		for (int i = 0; i < 10; i++) {
			thread = factory.newThread(task);
			thread.start();
		}
		
		System.out.printf("Factory stats:\n");
		System.out.printf("%s\n",factory.getStats());

	}

}

class MyThreadFactory implements ThreadFactory {

	private int counter;
	private String name;
	private List<String> stats;

	public MyThreadFactory(String name) {
		counter = 0;
		this.name = name;
		stats = new ArrayList<String>();
	}

	@Override
	public Thread newThread(Runnable r) {
		Thread t = new Thread(r, name + "-Thread_" + counter);
		counter++;
		stats.add(String.format("Created thread %d with name %s on %s\n",
				t.getId(), t.getName(), new Date()));
		return t;
	}

	public String getStats() {
		StringBuffer buffer = new StringBuffer();
		Iterator<String> it = stats.iterator();
		while (it.hasNext()) {
			buffer.append(it.next());
			buffer.append("\n");
		}
		return buffer.toString();
	}
}

class Task456 implements Runnable {
	@Override
	public void run() {
		try {
			TimeUnit.SECONDS.sleep(1);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
}
